package core.proto.annotation;

import java.awt.Point;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.io.FilenameUtils;

import core.proto.Util;
import core.proto.annotation.AnnotationModel.AnnotationLocation;

import static app.constants.CollabVizConstants.*;

/**
 * Central in-memory repo for all annotations created thus far, and is responsible 
 * for serializing them.  
 * @author Wei Xin Yuan
 *
 */
public class AnnotationManager {
	private static Hashtable<String, ArrayList<Annotation>> store; 
	final static int ARRAYLIST_INIT_CAP = 16;
	
	static {
		File f = new File(ANNOTATIONS_FOLDER);
		if (! f.exists()){
			f.mkdir();
		}
		store = new Hashtable<String, ArrayList<Annotation>>();
		
		// load up the store.
		// for now just read the directory. Annotations
		if (f.isDirectory()){
			File[] annotations = f.listFiles();
			BufferedReader reader; 
			for (File annoFile : annotations){
				try {
					reader = new BufferedReader(new FileReader(annoFile));
					String line;
					String out = "";
					String concat = "";
					while ((line = reader.readLine()) != null){
						out = out + line;
						
					}
					
					String[] lines = out.split("<END>");
					for(int i = 0; i < lines.length; i++){
						if (! lines[i].trim().equals("")){
							try{
								Annotation a = new Annotation(lines[i]);
								if(a != null){
									if (! store.containsKey(a.getModel().getDocKey())){
										store.put(a.getModel().getDocKey(), new ArrayList<Annotation>(ARRAYLIST_INIT_CAP));
									}
								}
								store.get(a.getModel().getDocKey()).add(a);
							}
							catch(Error e){
								System.out.println(e);
							}
						}
					}
					
					
					/*while ((line = reader.readLine()) != null){
						if (! line.trim().equals("")){
							try{
								Annotation a = new Annotation(line);
								System.out.println("LINE " + line);
								//System.out.println(store.size());
								//System.out.println(a.getModel());
								if(a != null){
									if (! store.containsKey(a.getModel().getDocKey())){
										store.put(a.getModel().getDocKey(), new ArrayList<Annotation>(ARRAYLIST_INIT_CAP));
									}
								}
								store.get(a.getModel().getDocKey()).add(a);
							}
							catch(Error e){
								System.out.println(e);
							}
						}
					}*/
					
				} catch (FileNotFoundException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	/**
	 * When this is called, the annotation, highlight file for the case with 
	 * the given key is updated. 
	 * @param key Usually the case name. 
	 */
	public static void writeFile(String key){
		File f = new File(FilenameUtils.concat(ANNOTATIONS_FOLDER, key + ".txt"));
		if (f.exists()){
			f.delete(); // clean start. 
		}
		PrintWriter writer = null;
		if (store.containsKey(key) && store.get(key).size() > 0){
			try {
				writer = new PrintWriter(new FileWriter(f));

				ArrayList<Annotation> annos = store.get(key);
				
				for(int i = annos.size() - 1; i >= 0; --i) {
					if (annos.get(i).getModel().isDelete()){
						annos.remove(i);
					} else {
						writer.println(annos.get(i).toSerializeString());
					}
				}
			} catch (IOException e) {
				System.err.println(e.getStackTrace());
			} finally {
				if (writer != null){
					writer.flush();
					writer.close();
				}
			}
		}
	}

	public static void addAnnotation(String key, Annotation value){
		if (! store.containsKey(key)){
			store.put(key, new ArrayList<Annotation>(ARRAYLIST_INIT_CAP));
		}
		store.get(key).add(value);
	}

	public static void removeAnnotation(String key, Annotation value){
		if (store.containsKey(key)){
			store.get(key).remove(value);
		}
	}
	
	public static Iterable<Annotation> getAnnotations(String key, AnnotationLocation loc) {
		LinkedList<Annotation> output = new LinkedList<Annotation>();
		if (store.containsKey(key)) {
			for(Annotation anno : store.get(key)) {
				if (anno.getModel().getLocation() == loc) {
					output.add(anno);
				}
			}
		}
		return output;
	}
	
	public static Iterable<Annotation> getAnnotations(String key){
		if (store.containsKey(key)){
			return store.get(key);
		}		
		return new LinkedList<Annotation>();
	}
	
	public static Iterable<Annotation> getAllAnnotationsAt (AnnotationLocation loc) {
		List<Annotation> annos = new LinkedList<Annotation>();
		for(List<Annotation> l : store.values()){
			for (Annotation a : l){
				if (a.getModel().getLocation() == loc){
					annos.add(a);
				}
			}
		}
		return annos;
	}
	
	public static AnnotationModel getModelFromUI(AnnotationUI au, AnnotationModel.AnnotationLocation location){
		for(Annotation anno : AnnotationManager.getAllAnnotationsAt(location)){
			if(anno.getView() == au){
				return anno.getModel();
			}
		}
		return null;
	}
	
}
